package server;

import common.LogUtil;
import common.ProxyMapping;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * 代理服务实现
 */
public class ProxyService {
    private static final Logger logger = LogUtil.getLogger(ProxyService.class.getName());

    // 关联的代理管理器
    private final ProxyManager proxyManager;

    // 代理配置
    private final ProxyMapping config;

    // 服务器socket通道
    private ServerSocketChannel serverChannel;

    // 选择器
    private Selector selector;

    // 运行标志
    private volatile boolean running = false;

    /**
     * 构造函数
     */
    public ProxyService(ProxyManager proxyManager, ProxyMapping config) {
        this.proxyManager = proxyManager;
        this.config = config;
    }

    /**
     * 启动代理服务
     */
    public void start() throws IOException {
        if (running) {
            return;
        }

        // 初始化服务器通道
        selector = Selector.open();
        serverChannel = ServerSocketChannel.open();
        serverChannel.configureBlocking(false);
        serverChannel.socket().bind(new InetSocketAddress(config.getListenPort()));
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 设置运行标志
        running = true;

        logger.info("Proxy service started: " + config.getName() +
                " on port " + config.getListenPort() +
                " with protocol " + config.getProtocol());

        // 开始接受连接
        proxyManager.getServer().getExecutor().execute(this::acceptLoop);
    }

    /**
     * 连接接受循环
     */
    private void acceptLoop() {
        try {
            while (running) {
                if (selector.select(1000) > 0) {
                    Iterator<SelectionKey> keys = selector.selectedKeys().iterator();

                    while (keys.hasNext()) {
                        SelectionKey key = keys.next();
                        keys.remove();

                        if (!key.isValid()) {
                            continue;
                        }

                        if (key.isAcceptable()) {
                            acceptConnection();
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.log(Level.SEVERE, "Error in accept loop: " + config.getName(), e);
        }
    }

    /**
     * 接受新连接
     */
    private void acceptConnection() {
        try {
            SocketChannel userChannel = serverChannel.accept();
            if (userChannel != null) {
                userChannel.configureBlocking(false);

                // 创建用户连接
                UserConnection connection = proxyManager.createUserConnection(this, userChannel);

                // 处理新连接
                connection.start();
            }
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Error accepting connection: " + config.getName(), e);
        }
    }

    /**
     * 停止代理服务
     */
    public void stop() {
        if (!running) {
            return;
        }

        running = false;

        try {
            if (serverChannel != null) {
                serverChannel.close();
            }

            if (selector != null) {
                selector.close();
            }

            logger.info("Proxy service stopped: " + config.getName());
        } catch (IOException e) {
            logger.log(Level.SEVERE, "Error stopping proxy service: " + config.getName(), e);
        }
    }

    /**
     * 获取代理管理器
     */
    public ProxyManager getProxyManager() {
        return proxyManager;
    }

    /**
     * 获取代理配置
     */
    public ProxyMapping getConfig() {
        return config;
    }
}
